《前端实战》之变量提升,函数声明提升及变量作用域详解
之所以会写这篇文章,主要源于笔者在重构老项目的时候发现了一个bug,导致某个插件不生效了,在review加search code加断点调试之后,发现了原因:一个同名的变量将插件方法给覆盖了,ohmyGad。
正文
1.变量是如何被覆盖的
a = 2;
console.log(a) // 2
a = function(){};
console.log(a) // function(){};
2.变量提升
console.log(a);
var a = 1;
console.log(b);
function b(){};
var a = undefined;
var b = undefined;
console.log(a)
// ..
console.log(b)
函数声明和变量声明总是会被解释器悄悄地被"提升"到方法体的最顶部。
值得注意的是,我们使用let,const定义变量的时候,并不会发生提升,因为它存在局部(块)作用域的概念,会出现暂时性死区,所以在它们之前打印变量将报错。如果对暂时性死区或者对es6不太了解的朋友可以参考我的另一篇文章:
对let和const以及es6的新特性有详细的介绍。
3.更近一步——变量提升的优先级
var a = 1;
function a(){
console.log(a)
}
console.log(a)
4.函数参数作用域与作用域链
作用域就是变量和函数的可访问范围,当代码在一个环境中执行时,会创建变量对象的一个作用域链(scope chain),来保证对执行环境有权访问的变量和函数的顺序访问。作用域第一个对象始终是当前执行代码所在环境的变量对象。然后会一层层向外查找,直到发现第一个指定的变量为止。
在了解完以上概念之后,我们来看看下面这个问题:
var a = {name: 'xuxi'};
function b(a){
a.age = 12;
a = {num: 1};
return a
}
var a1 = b(a);
console.log(a, a1)
这块主要还是函数内部作用域和引用类型的一个问题。具体过程如下:
(1)我们根据之前介绍的作用域和作用域链的概念可以知道,在函数体内,变量会就近查找,而函数参数会存在于函数体内部作用域中,所以当我们把全局变量a当作入参传递给函数时,又由于全局a是引用类型,此时只是引用了它的地址,那么我们通过a.age设置属性时,全局a也会改变。
总结
函数声明提升,变量作用域以及作用域链这块一直是学习javascript的基础也是重点,所以希望这篇文章可以让大家更好的掌握它。 如果想了解更多webpack,node,gulp,css3,javascript,nodeJS,canvas等前端知识和实战,欢迎在公众号《趣谈前端》加入我们一起学习讨论,共同探索前端的边界。
更多推荐
欢迎关注下方公众号,获取更多前端知识精粹和学习社群:在公众号点击进群,可以加入vue学习小组,一起学习前端技术;
回复 学习路径,将获取笔者多年从业经验的前端学习路径的思维导图
趣谈前端
Vue、React、小程序、Node
前端 算法|性能|架构|安全